#include "./log_uart.h"
#include "../xlib/gpio.h"
#include "../xlib/dma.h"
#include "../xlib/uart.h"
#include <stdio.h>
#include <stdarg.h>

namespace driver {

LogUart logUart;

namespace log_uart {

using namespace stm32f1;

using TX = gpio::Cfg<gpio::PB<10>, gpio::Mode::OUT_50MHz_AF_PP>;
using RX = gpio::Cfg<gpio::PB<11>, gpio::Mode::INPUT_FLOAT>;
using UART = uart::Uart3;
using DMA_TX = dma::DmaSel<UART::BASE_VAL>::TX_CHAN;
using DMA_RX = dma::DmaSel<UART::BASE_VAL>::RX_CHAN;

}

using namespace log_uart;

void LogUart::init() {
    m_flags.init();
    m_flags.set_flags(FLAG_DMA_TC);

    rcc::enable<TX, RX, UART, DMA_TX, DMA_RX>();
    gpio::config<RX, TX>();
    UART::set_cfg<uart::DefCfg2>();
    // DMA_RX::set_cfg<dma::UartRecvCfg, UART::DR_ADDR_VAL>(
    //     reinterpret_cast<uint32_t>(m_recv_buf), RECV_BUF_SIZE);
   // NVIC_EnableIRQ(USART1_IRQn);
    NVIC_EnableIRQ(DMA1_Channel2_IRQn);
}

void LogUart::write_by_dma(const void *buf, uint16_t len) {
    DMA_TX::set_cfg<dma::UartWriteCfg, UART::DR_ADDR_VAL>(
        reinterpret_cast<uint32_t>(buf), len);
}

void LogUart::printf(const char *format, ...) {
    m_flags.wait_any_flags(FLAG_DMA_TC);
    va_list ap;
    va_start(ap, format);
    int n = vsprintf(m_write_buf, format, ap);
    write_by_dma(m_write_buf, n);
}

}

using namespace driver;


extern "C" void DMA1_Channel2_IRQHandler() {
    if (DMA_TX::is_tc()) {
        DMA_TX::clear_flags();
        logUart.on_dma_tc();
    }
}



